﻿// <copyright file="TrackMultiScaleImage.cs" company="Microsoft">
// Copyright (c) 2010 Microsoft All Rights Reserved
// </copyright>
// <author>Microsoft</author>
// <email>mischero@microsoft.com</email>
// <date>2010-01-01</date>
// <summary>Web analytics service behavior class definition</summary>

namespace Microsoft.WebAnalytics.Media
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Interactivity;
    using System.Windows.Markup;
    using Microsoft.WebAnalytics;

    /// <summary>
    /// <img src="../media/Microsoft.WebAnalytics.Media.TrackMultiScaleImage.24x24.png"/> 
    /// Track Deep Zoom Events 
    /// </summary>
    [ContentProperty("Locations")]
    public class TrackMultiScaleImage : Behavior<MultiScaleImage>
    {
        /// <summary>
        /// Initializes a new instance of the TrackMultiScaleImage class.
        /// </summary>
        public TrackMultiScaleImage()
        {
            this.Locations = new ObservableCollection<MultiScaleImageLocation>();
        }

        #region Properties

        /// <summary>
        /// Gets the locations to track
        /// </summary>
        public ObservableCollection<MultiScaleImageLocation> Locations { get; private set; }

        /// <summary>
        /// Gets or sets the event Logging method
        /// </summary>
        [Import("Log")]
        public Action<AnalyticsEvent> Log { get; set; }
        #endregion

        #region Methods
        /// <summary>
        /// Attach events and initialize parts
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

#if WINDOWS_PHONE
            CompositionInitializer.SatisfyImports(this);
#else
            PartInitializer.SatisfyImports(this);
#endif

            this.AssociatedObject.ViewportChanged += new RoutedEventHandler(this.OnViewportChanged);
        }

        /// <summary>
        /// Detach events
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.AssociatedObject.ViewportChanged -= new RoutedEventHandler(this.OnViewportChanged);
        }

        #endregion

        #region Implementation
        /// <summary>
        /// Use the Pythagorean Theorum to get the distance between two points
        /// </summary>
        /// <param name="p1">the first point</param>
        /// <param name="p2">the second point</param>
        /// <returns>the distance between the two points</returns>
        private static double Distance(Point p1, Point p2)
        {
            return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
        }

        /// <summary>
        /// Viewport changed event handler
        /// </summary>
        /// <param name="sender">the multiscale image</param>
        /// <param name="e">the routed event argument</param>
        private void OnViewportChanged(object sender, RoutedEventArgs e)
        {
            var hitLocations = from location in this.Locations
                               where Math.Abs(this.AssociatedObject.ViewportWidth - location.ViewportWidth) <= location.WidthTolerance &&
                                    Distance(this.AssociatedObject.ViewportOrigin, location.ViewportOrigin) <= location.OriginTolerance
                               select new AnalyticsEvent()
                               {
                                   EventArgs    = location.CustomProperties,
                                   Name         = "LocationNear",
                                   ObjectName   = this.AssociatedObject.Name,
                                   ObjectType   = this.AssociatedObject.GetType().ToString(),
                                   ActionValue  = location.Name,
                               };

            foreach (var logEvent in hitLocations)
            {
                this.Log(logEvent);
            }
        }

        #endregion
    }
}
